package com.google.code.chaotic.updates;

import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.ejb.EJB;
import javax.naming.InitialContext;
import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.TypedQuery;

import org.restlet.resource.ClientResource;
import org.restlet.resource.Get;
import org.restlet.resource.ServerResource;

import com.google.code.chaotic.ConversionUtil;
import com.google.code.chaotic.EmFactory;
import com.google.code.chaotic.dto.CommuterDto;
import com.google.code.chaotic.dto.CommutingServiceDto;
import com.google.code.chaotic.ejb.AnalysisTimerLocal;
import com.google.code.chaotic.model.CommutingService;

/**
 * Resource which has only one representation.
 * 
 */
public class BackTierStarterResourceImpl extends ServerResource //
		implements BackTierStarterResource {

	private static Logger logger = Logger
			.getLogger(BackTierStarterResourceImpl.class.getName());

	@EJB
	private AnalysisTimerLocal timer;

	//

	@Get
	@Override
	public String start() {
		logger.info("\"start\" request received!");
		new Thread(new Runnable() {
			@Override
			public void run() {
				EntityManager em = null;
				try {
					em = EmFactory.get().createEntityManager();
					EntityTransaction tx = em.getTransaction();

					String frontTierUrl = BackTierWebContextListener
							.getFrontTierUrl();
					String restUrl1 = frontTierUrl + "/updates/list";

					ClientResource clientResource1 = new ClientResource(
							restUrl1);

					FrontTierUpdatesResource frontUpdates = clientResource1
							.wrap(FrontTierUpdatesResource.class);

					tx.begin();
					// TODO: The following two deletions must be removed
					// when incremental updates is implemented.
					em.createQuery("DELETE FROM HabitInService his")
							.executeUpdate();
					em.createQuery("DELETE FROM ServiceWaypoint sw")
							.executeUpdate();
					em.createQuery("DELETE FROM CommutingService s")
							.executeUpdate();
					em.createQuery("DELETE FROM HabitWaypoint hw")
							.executeUpdate();
					em.createQuery("DELETE FROM CommutingHabit h")
							.executeUpdate();
					em.createQuery("DELETE FROM Commuter c").executeUpdate();

					int offset = 0;
					int maxCount = 10;
					int actualCount = maxCount;

					while (maxCount == actualCount) {
						CommuterDto[] commuters = frontUpdates
								.listCommuters(maxCount);

						actualCount = commuters.length;
						offset += actualCount;

						for (CommuterDto dto : commuters) {
							logger.info(String.format(
									">>>>> Persisting commuter %1$s : %2$s",
									dto.getId(), dto.toString()));

							em.persist(ConversionUtil.dtoToEntity(dto));
						}
					}
					tx.commit();

					if (timer == null) {
						InitialContext ctx = new InitialContext();
						timer = (AnalysisTimerLocal) ctx.lookup(//
								"java:global/backTier/backTierEJB/AnalysisTimer!com.google.code.chaotic.ejb.AnalysisTimerLocal");

						logger.info("The instance of "
								+ AnalysisTimerLocal.class.getSimpleName()
								+ " was found using context lookup.");

					} else {
						logger.info("The instance of "
								+ AnalysisTimerLocal.class.getSimpleName()
								+ " was injected by the container.");
					}
					timer.fireScheduledTimeout();
					logger.info(">>>>> My temporary checkpoint #1!");

					TypedQuery<CommutingService> query = em.createQuery(
							"SELECT s FROM CommutingService s ORDER BY s.id",
							CommutingService.class);
					List<CommutingService> services = query.getResultList();
					for (CommutingService entity : services) {
						logger.info(String.format(
								"Adding CommutingService #%s", //
								entity.getId()));

						CommutingServiceDto dto = ConversionUtil
								.entityToDto(entity);

						@SuppressWarnings("unused")
						String id = frontUpdates.addCommutingService(dto);
					}
					logger.info(">>>>> My temporary checkpoint #2!");

				} catch (Throwable e) {
					logger.log(Level.SEVERE, e.toString(), e);

				} finally {
					if (em != null)
						em.close();
				}
			}
		}).start();
		return "BackTier update started.";
	}
}